package booyah.service;

import java.util.List;
import java.util.Random;

import org.springframework.orm.jpa.JpaTemplate;
import org.springframework.orm.jpa.support.JpaDaoSupport;

import booyah.application.User;

public class UserServiceImpl extends JpaDaoSupport implements UserService {

    public void createUser(final User user) {
        if (user.getId() != null)
            throw new IllegalArgumentException("Not a new user.");
        getJpaTemplate().persist(user);
    }

    public void updateUser(final User user) {
        JpaTemplate jpaTemplate = getJpaTemplate();
        jpaTemplate.persist(jpaTemplate.contains(user) ? user : jpaTemplate.merge(user));
    }

    public void deleteUser(User user) {
        JpaTemplate jpaTemplate = getJpaTemplate();
        jpaTemplate.remove(jpaTemplate.contains(user) ? user : jpaTemplate.merge(user));
    }

    public User authenticate(String email, String password) {
        assert (email != null);
        assert (password != null);
        User user = findUserByEmail(email);
        // TODO This should incorporate MD5 hash or some other mechanism to
        // protect the password.
        if (user != null && password.equals(user.getPassword())) {
            return user;
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public String resetPassword(String email) {
        List<User> users = getJpaTemplate().find("from User p where p.email = ?", email);
        assert (users.size() < 2);
        return users.size() == 0 ? null : resetPassword(users.get(0));
    }

    public String resetPassword(User user) {
        String newPassword = generateRandomString(8);
        user.setPassword(newPassword);
        updateUser(user);
        return newPassword;
    }

    static protected String generateRandomString(final int length) {
        String charset = "!0123456789abcdefghijklmnopqrstuvwxyz";
        Random rand = new Random(System.currentTimeMillis());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i <= length; i++) {
            int pos = rand.nextInt(15);
            sb.append(charset.charAt(pos));
        }
        return sb.toString();
    }

    public User findUserById(Long id) {
        List<User> users = getJpaTemplate().find("from User u where u.id = ?", id);
        assert (users.size() == 1);
        return users.get(0);
    }

    @SuppressWarnings("unchecked")
    public User findUserByEmail(String email) {
        List<User> users = getJpaTemplate().find("from User p where p.email = ?", email);
        assert (users.size() < 2);
        return users.isEmpty() ? null : users.get(0);
    }

}
